package pers.andy.websocket.spring;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import pers.andy.websocket.cache.SystemCache;

/**
 * spring websocket处理器
 * @author Andy.ye
 * @date 2018年3月29日 下午3:00:35
 */
@Service
public class MeetingWebSocketHandler extends TextWebSocketHandler {

	private static final Log LOG = LogFactory.getLog(MeetingWebSocketHandler.class);
	// 会议id和wsSession列表
	private static final ConcurrentHashMap<Integer, CopyOnWriteArraySet<WebSocketSession>> meetingWsSeesionMap = new ConcurrentHashMap<>();

	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
		LOG.info("spring websocket成功建立连接...");
		int meetingId = getMeetingId(session);
		if (meetingId <= 0) {
			singleMessage(session, new TextMessage("会议不存在!"));
			session.close();
		}
		// 如果该会议已存在，则直接加入
		if (meetingWsSeesionMap.containsKey(meetingId)) {
			CopyOnWriteArraySet<WebSocketSession> webSocketSessions = meetingWsSeesionMap.get(meetingId);
			webSocketSessions.add(session);
		}
		// 如果不存在，则新建
		else {
			CopyOnWriteArraySet<WebSocketSession> webSocketSessions = new CopyOnWriteArraySet<>();
			webSocketSessions.add(session);
			meetingWsSeesionMap.put(meetingId, webSocketSessions);
		}
	}

	@Override
	public void handleTextMessage(WebSocketSession session, TextMessage message) {
		if (!session.isOpen())
			return;
		LOG.info(message.getPayload());
		int meetingId = getMeetingId(session);
		TextMessage wsMessage = new TextMessage(message.getPayload());
		broadcastMessage(meetingId, wsMessage);
	}

	/**
	 * 发送信息给指定用户
	 * @param clientId
	 * @param message
	 * @return
	 */
	public void singleMessage(WebSocketSession session, TextMessage message) {
		if (!session.isOpen())
			return;
		try {
			session.sendMessage(message);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 广播信息
	 * @param message
	 * @return
	 */
	public void broadcastMessage(int meetingId, TextMessage message) {
		// 获取会议所有的wsSession
		CopyOnWriteArraySet<WebSocketSession> webSocketSessions = meetingWsSeesionMap.get(meetingId);
		for (WebSocketSession session : webSocketSessions) {
			try {
				if (session.isOpen()) {
					session.sendMessage(message);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
		if (session.isOpen()) {
			session.close();
		}
		LOG.info("连接出错");
	}

	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
		LOG.info("连接已关闭：" + status);
		int meetingId = getMeetingId(session);
		// role 1为主持人
		String role = String.valueOf(session.getAttributes().get("role"));
		// 如果是主持人，则关闭所有该会议连接
		CopyOnWriteArraySet<WebSocketSession> webSocketSessions = meetingWsSeesionMap.get(meetingId);
		if (StringUtils.equals("1", role)) {
			SystemCache.idRandStrMap.remove(meetingId);
			for (WebSocketSession webSocketSession : webSocketSessions) {
				webSocketSession.close();
			}
			webSocketSessions.remove(meetingId);
		} else {
			webSocketSessions.remove(session);
		}
	}

	@Override
	public boolean supportsPartialMessages() {
		return false;
	}

	private int getMeetingId(WebSocketSession session) {
		String randStr = String.valueOf(session.getAttributes().get("randStr"));
		int meetingId = SystemCache.getMeetingIdByRandStr(randStr);
		return meetingId;
	}
}